package ar.edu.utn.frba.dds.opendesigners.dominio;

import java.util.ArrayList;
import java.util.List;

import org.uqbar.commons.model.Entity;
import org.uqbar.commons.model.UserException;
import org.uqbar.commons.utils.Observable;
import org.uqbar.commons.utils.Transactional;

import ar.edu.utn.frba.dds.opendesigners.ParametroBusqueda;
import ar.edu.utn.frba.dds.opendesigners.excepciones.ExcepcionAsientoReservado;
import ar.edu.utn.frba.dds.opendesigners.excepciones.ExcepcionNegocio;
import ar.edu.utn.frba.dds.opendesigners.excepciones.ExcepcionSobreReservaAsiento;
import ar.edu.utn.frba.dds.opendesigners.fecha.Fecha;
import ar.edu.utn.frba.dds.opendesigners.formato.FormatoSimple;
import ar.edu.utn.frba.dds.opendesigners.resultados.Asiento;
import ar.edu.utn.frba.dds.opendesigners.resultados.AsientoGridItem;
import ar.edu.utn.frba.dds.opendesigners.resultados.ResultadoBusqueda;
import ar.edu.utn.frba.dds.opendesigners.user.Usuario;

@SuppressWarnings("serial")
@Transactional
@Observable
public class BusquedasModel extends Entity{
        
        private String origen;
        private String destino;
        private String fecha;
        
        private AsientoGridItem asientoSeleccionado;
        private List<AsientoGridItem> resultados;
        
//        private AgenteDeViaje agente;
        private Usuario usuario;
//        private Reservas objReservas;
        
        public BusquedasModel(Usuario usuario){
//                LanchitaAdapter adapterLanchita = new LanchitaAdapter(new LanchitaMoke(), Reservas.getInstance());
//                OceanicAdapter adapterOceanic = new OceanicAdapter( new OceanicMoke(), Reservas.getInstance());
//                agente = AgenteDeViaje.getInstance();
//                objReservas = Reservas.getInstance();
                this.usuario = usuario;

//                agente.agregarAerolinea(adapterLanchita);
//                agente.agregarAerolinea(adapterOceanic);
        }
        
        public String getOrigen() {             
                return origen;
        }
        
        public void setOrigen(String origen) {
                this.origen = origen.toUpperCase();
        }
        public String getDestino() {
                return destino;
        }
        public void setDestino(String destino) {
                this.destino = destino.toUpperCase();
        }
        public String getFecha() {
                return fecha;
        }
        public void setFecha(String fecha) {

                this.fecha = fecha;
        }
        
        public boolean ingresoOrigen() {
                return this.getOrigen() != null && !this.getOrigen().trim().equals("");
        }
        
        public boolean ingresoDestino() {
                return this.getDestino() != null && !this.getDestino().trim().equals("");
        }
        
        public boolean ingresoFecha(){
                return this.getFecha() != null && !this.getFecha().trim().equals("");
        }

        public List<AsientoGridItem> transformarAsientos(ResultadoBusqueda resultados){
                List<AsientoGridItem> resultadoGrid = new ArrayList<AsientoGridItem>();
                
                for(Asiento asiento : resultados.getListaResultados()){
                        AsientoGridItem asientoGrid = new AsientoGridItem();
                        asientoGrid.setNombreAerolinea(asiento.getNombreAerolinea());
                        asientoGrid.setNumeroVuelo(asiento.getNumeroVuelo());
                        asientoGrid.setNumeroAsiento(asiento.getNumeroAsiento());
                        asientoGrid.setPrecio(asiento.getPrecio());
                        asientoGrid.setTipo(asiento.getTipo());
                        asientoGrid.setUbicacion(asiento.getUbicacion());
                        
                        //Agrego esto porque necesito la referencia al asiento real para realizar operaciones sobre el.
                        asientoGrid.setAsientoReal(asiento);
                        
                        resultadoGrid.add(asientoGrid);
                }
                
                return resultadoGrid;
        }
        public AsientoGridItem getAsientoSeleccionado() {
                return asientoSeleccionado;
        }

        public void setAsientoSeleccionado(AsientoGridItem asientoSeleccionado) {
                this.asientoSeleccionado = asientoSeleccionado;
        }

        public List<AsientoGridItem> getResultados() {
                return resultados;
        }

        public void setResultados(List<AsientoGridItem> resultados) {
                this.resultados = resultados;
        }

//        public AgenteDeViaje getAgente() {
//                return agente;
//        }
//
//        public void setAgente(AgenteDeViaje agente) {
//                this.agente = agente;
//        }
        
        public void buscar(){
                
                this.validar();
                
                FormatoSimple formatoFecha = new FormatoSimple("dd/MM/yyyy");
                Fecha fechaBuscada = new Fecha(formatoFecha.crear(this.getFecha())); 
                
                ParametroBusqueda busqueda = new ParametroBusqueda(this.getOrigen(), this.getDestino(), fechaBuscada.stringFecha("dd/MM/yyyy"));
                busqueda.setIncluyeAsientosReservados(true);
                //ResultadoBusqueda resultados = AgenteDeViaje.getInstance().buscar(busqueda);
                ResultadoBusqueda resultados = this.usuario.buscar(busqueda);
                
                this.resultados = this.transformarAsientos(resultados);
        }

        public void validar(){
                if (!this.ingresoOrigen()){
                        throw new UserException("Debe ingresar el origen");
                }
                
                if (!this.ingresoDestino()){
                        throw new UserException("Debe ingresar el destino");
                }
                
                if (!this.ingresoFecha()){
                        throw new UserException("Debe ingresar una fecha valida");
                }

        }
        
        public void verificarItemSeleccionado(){
                if (this.asientoSeleccionado == null){
                        throw new UserException("Debe seleccionar un asiento");
                }
        }
        
        public void limpiar() {
                this.asientoSeleccionado = null;
                this.resultados = null;
        }
        
        public void comprar(){
                try{
                        this.verificarItemSeleccionado();
                       	//this.asientoSeleccionado.getAsientoReal().comprar();
                        this.usuario.comprar(this.asientoSeleccionado.getAsientoReal());
                
                //catch(UserException ex){
                }catch(ExcepcionNegocio ex){
                	throw new UserException("Ha ocurrido un error en su compra: " + ex.getMessage() + ". Por favor intente nuevamente");
                }

        }
        
        public void reservar(){
                try{
                        
                        this.verificarItemSeleccionado();
                        
                        this.usuario.reservar(this.asientoSeleccionado.getAsientoReal());
//                        if (!this.objReservas.estaAsientoReservado(this.asientoSeleccionado.getAsientoReal())){
//                                throw new ExcepcionAsientoReservado("El asiento ya se encuentra reservado.");
//                                this.objReservas.reservar(this.asientoSeleccionado.getAsientoReal(), this.getUsuario());
//                        }else{
//                                throw new ExcepcionAsientoReservado("El asiento ya se encuentra reservado.");
//                        }
                }
                catch(ExcepcionAsientoReservado ex){
                        throw new UserException("Ha ocurrido un error en su reserva: " + ex.getMessage() + ". Por favor intente nuevamente");
                }
        }
        
        public void sobrereservar(){
                try{
                        this.verificarItemSeleccionado();

                        //this.asientoSeleccionado.getAsientoReal().reservar();
                        this.usuario.reservar(this.asientoSeleccionado.getAsientoReal());
                        
                }
                catch(ExcepcionSobreReservaAsiento ex){
                        throw new UserException("Ha ocurrido un error en su reserva: " + ex.getMessage() + ". Por favor intente nuevamente");
                }
        }

        public void setUsuario(Usuario cuentaUsuario) {
                this.usuario = cuentaUsuario;
        }
        
        public Usuario getUsuario(){
                return this.usuario;
        }
}
